<?php
declare(strict_types=1);


namespace Reven\Web3;


use BitWasp\Bitcoin\Key\Factory\HierarchicalKeyFactory;
use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39SeedGenerator;
use BitWasp\Bitcoin\Mnemonic\MnemonicFactory;
use kornrunner\Ethereum\Address;
use Reven\Result\Re;
use Web3p\EthereumUtil\Util;

class EtherAccount extends Help
{
    // composer require protonlabs/bitcoin
    // composer require web3p/ethereum-util
    // composer require kornrunner/ethereum-address

    /**
     * 生成助记词
     * @param int $entropySize
     * @return Re
     */
    public static function  mnemonic(int $entropySize=128):Re {
        try {
            $mnemonicFactory = MnemonicFactory::bip39();
            $mnemonic= $mnemonicFactory->create($entropySize);
            return self::re($mnemonic);
        }catch (\Throwable $e){
            return self::reFail($e->getMessage())->setCode('500');
        }
    }

    /**
     * @param string $private
     * @return Re
     */
    public static function newEthAccount(string $private=''):Re{
        try {
            $address = new Address($private);
            return self::re([
                'address'=> '0x'.$address->get(),
                'private'=>$address->getPrivateKey(),
                'public'=>$address->getPublicKey(),
                'seed'=> '',
                'mnemonic'=>''
            ]);
        }catch (\Throwable $e){
            if ($private)return self::reFail("private fail");
            return self::reFail($e->getMessage())->setCode('500');
        }

    }

    /**
     * 助记词生成钱包
     * @param string $mnemonic
     * @return Re
     */
    public static function mnemonicEthAccount(string $mnemonic):Re{
        try {
            $seedGenerator = new Bip39SeedGenerator();

            $seed = $seedGenerator->getSeed($mnemonic);
            $hdFactory = new HierarchicalKeyFactory();
            $master = $hdFactory->fromEntropy($seed);

            // 设置路径account
            $hardened = $master->derivePath("44'/60'/0'/0/0");
            $util = new Util();
            $address= $util->publicKeyToAddress($util->privateKeyToPublicKey($hardened->getPrivateKey()->getHex()));
            $data= [
                'address'=> $address,
                'private'=>$hardened->getPrivateKey()->getHex(),
                'public'=>$hardened->getPublicKey()->getHex(),
                'seed'=> $seed->getHex(),
                'mnemonic'=>$mnemonic
            ];

            return self::re($data);
        }catch (\Throwable $e){
            return self::reFail()->setCode('500');
        }
    }
}